昨日提到的Gamma矯正是為了矯正曝光問題,那麼Beta矯正就是為了解決影像對比度問題。
影像對比是指影像中暗的地方是否夠暗,亮的地方是否夠亮。而人類視覺對於影像對比的敏感度比絕對亮度高,因此通常會覺得高對比度的影像品質較佳。
Beta矯正的程式碼如下:
import numpy as np
import cv2
import scipy.special as special
img1 = cv2.imread("D:\Desktop\IThome\lena.bmp", -1)
def beta_correction(f, a = 2.0, b = 2.0):
g = f.copy()
nr, nc = f.shape[:2]
x = np.linspace(0, 1, 256)
table = np.round(special.betainc(a, b, x) * 255, 0)
if f.ndim != 3:
for x in range(nr):
for y in range(nc):
g[x, y] = table[f[x, y]]
else:
for x in range(nr):
for y in range(nc):
for k in range(3):
g[x, y, k] = table[f[x,y,k]]
return g
img2 = beta_correction(img1, a = 0.5, b = 0.5)
cv2.imshow("After", img2)
cv2.waitKey()
上述範例中,使用SciPy提供的特殊函數,可以用來計算Beta矯正的轉換函數,以實現影像對比的增強。
直方圖(histogram)的目的是用來統計數位影像中像素強度或色彩的分布情形,直方圖處理(Histogram Processing)是利用直方圖的影像增強技術。
數位影像中的直方圖可以定義如下:
其中,r_k為第k個強度值,n_k為強度r_k的像素個數
直方圖可以用來判斷影像的素質,例如曝光和對比度等等。如下圖所示:
當強度分布集中在高強度範圍,可以判斷為過曝,若集中在低強度範圍,可以判斷為曝光不足。若強度分布僅集中在部分強度範圍,則可判斷為低對比度(Low Contrast)影像
下面的程式碼為輸出一個影像的直方圖:
import numpy as np
import cv2
import matplotlib.pyplot as plt
def histogram(f):
if f.ndim != 3:
hist = cv2.calcHist([f], [0], None, [256], [0,256])
plt.plot(hist)
else:
color = ('b', 'g', 'r', 'b')
for i, col in enumerate(color):
hist = cv2.calcHist([f], [i], None, [256], [0,256])
plt.plot(hist, color = col)
plt.xlim([0,256])
plt.xlabel("Intensity")
plt.ylabel("#Intensities")
plt.show()
img = cv2.imread("D:\Desktop\IThome\lena.bmp", -1)
histogram(img)
#cv2.imshow("After", img2)
cv2.waitKey()
本程式採用OpenCV提供的calcHist函式計算直方圖,並利用matplotlib套件繪圖,且此程式同時適用於灰階和色彩影像。
以下就來介紹直方圖等化的演算法,說明如下:
(1) 首先計算機率密度函數(Probability Density Function,PDF),定義如下:
其中,k = 0,1,2...,L-1,計算每種強度的機率值,可以經由直方圖的結果計算而得(除以總像素個數)。
(2) 計算累積密度函數(Cumulative Density Function,CDF),定義如下:
(3) 計算影像的輸出值:
S = (L-1)*CDF
通常計算過後的結果可能為浮點數,取四捨五入後以8-bits資料型態儲存。
等化結果如下圖所示:
無論過曝;曝光不足、低對比等都可以用直方圖等化處理,而先前提過的Gamma矯正雖然可解決曝光問題,但須手動輸入參數,直方圖可怖須輸入參數即可解決不同的曝光問題。
下方程式碼為直方圖等化,請注意灰階影像和色彩影像須進行不同處理:
import numpy as np
import cv2
img1 = cv2.imread("D:\Desktop\IThome\lena_gray.jpg", -1)
# For Color
R, G, B = cv2.split(img1)
output1_R = cv2.equalizeHist(R)
output1_G = cv2.equalizeHist(G)
output1_B = cv2.equalizeHist(B)
img2 = cv2.merge((output1_R, output1_G, output1_B))
# For Gray
img2 = cv2.equalizeHist(img1)
cv2.imshow("Orignial", img1)
cv2.imshow("After", img2)
cv2.waitKey()